package com.marry.file.handle;

import com.marry.file.util.FileUtil;
import com.marry.file.vo.MultiFileParam;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ZeroCopyHttpOutputMessage;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.File;
import java.io.IOException;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @path：com.marry.file.handle.FileController.java
 * @className：FileController.java
 * @description：文件上传接口
 * @author：LiuYun
 * @dateTime：2021/7/14 0:36
 * @editNote：
 */
@RestController
@RequestMapping("marry/file")
public class FileController {

    @Value("${file.server.path}")
    private String serverPath;

    @Value("${file.upload.path}")
    private String uploadPath;

    /**
     * 文件上传
     * @param filePart
     * @return
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<String> upload(@RequestPart("file") FilePart filePart) throws IOException {
        System.out.println(filePart.filename());
        System.out.println(filePart.toString());
        String osName = "os.name";
        Path path = Files.createFile(Paths.get(uploadPath + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "-" + filePart.filename()));

        //NOTE 方法一
        AsynchronousFileChannel channel =
                AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
        DataBufferUtils.write(filePart.content(), channel, 0)
                .doOnComplete(() -> System.out.println("finish"))
                .subscribe();

        System.out.println(path);
        return Mono.just(serverPath + path);
    }

    /**
     * 文件批量上传
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploads", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Flux<String> upload(@RequestPart ("file") Flux<FilePart> file) {
        return file.map(filePart->{
            Path tempFile = null;
            try {
                tempFile = Files.createFile(Paths.get(uploadPath + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "-" + filePart.filename()));
                AsynchronousFileChannel channel =
                        AsynchronousFileChannel.open(tempFile, StandardOpenOption.WRITE);
                DataBufferUtils.write(filePart.content(), channel, 0)
                        .doOnComplete(() -> System.out.println("finish"))
                        .subscribe();
            } catch (IOException e) {
                e.printStackTrace();
            }
//            filePart.transferTo(tempFile.toFile());
            return serverPath + tempFile;
        });
    }

    /**
     * 分片上传
     * @param param
     * @return
     */
    @PostMapping(value = "/upload1", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<String> upload1(MultiFileParam param) throws IOException {
        String md5 = FileUtil.getMd5(param.getFile());

        Path path = Files.createFile(Paths.get(uploadPath + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "-" + param.getFile().filename()));

        //NOTE 方法一
        AsynchronousFileChannel channel =
                AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
        DataBufferUtils.write(param.getFile().content(), channel, 0)
                .doOnComplete(() -> System.out.println("finish"))
                .subscribe();

        System.out.println(path);
        return Mono.just(serverPath + path);
    }

    /**
     * 文件下载
     * @param response
     * @return
     * @throws IOException
     */
    @GetMapping("/download")
    public Mono<Void> downloadByWriteWith(ServerHttpResponse response) throws IOException {
        ZeroCopyHttpOutputMessage zeroCopyResponse = (ZeroCopyHttpOutputMessage) response;
        response.getHeaders().set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=ly.jpg");
        response.getHeaders().setContentType(MediaType.IMAGE_JPEG);

        Path path = Paths.get("C:/upload/ly.jpg");
        File file = path.toFile();
        return zeroCopyResponse.writeWith(file, 0, file.length());
    }

}
